﻿/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2017 @ ShenZhen ,China
*******************************************************************************/
#include "Tracer.h"
#include "StringFilter.h"

#define UNKNOWN_RULE     (-1)

StringFilter::StringFilter()
{
    clear();
}

StringFilter::~StringFilter()
{
    clear();
}

int StringFilter::findPosByRule(int currentPos,bool isStartFlag,int& ruleIndex)
{
    int pos = std::string::npos;
    int vectorSize = m_ruleVector.size();
    if (ruleIndex<0)
    {
        ruleIndex = UNKNOWN_RULE;
    }
    if (vectorSize>0 && (ruleIndex<vectorSize))
    {
        if (UNKNOWN_RULE==ruleIndex)
        {
            for(int i=0; i< vectorSize; i++)
            {
                if (isStartFlag)
                {
                    pos = m_filterBuffer.find(m_ruleVector[i].startFlag,currentPos);
                }
                else
                {
                    pos = m_filterBuffer.find(m_ruleVector[i].endFlag,currentPos);
                }
                if (pos!=std::string::npos)
                {
                    ruleIndex=i;
                    return pos;
                }
            }
        }
        else
        {
            if (isStartFlag)
            {
                pos = m_filterBuffer.find(m_ruleVector[ruleIndex].startFlag,currentPos);
            }
            else
            {
                pos = m_filterBuffer.find(m_ruleVector[ruleIndex].endFlag,currentPos);
            }
            return pos;
        }
    }
    return pos;
}
/**
 *  \brief  字符串筛查
 *  \param  buf  要筛查的字串
 *  \param  size buf的长度
 *  \return 返回筛查到的符合规则的字符串
 */
std::vector<std::string> StringFilter::filterOn(const char* buf,int size)
{
    std::string filterString(buf,size);
    std::vector<std::string> strVector;
    if (!filterString.empty())
    {
        m_filterBuffer += filterString;
    }
    int currentPos=0;
    int startPos = -1;
    int endPos = -1;
    int unFilterPos=0;
    int ruleIndex = UNKNOWN_RULE;
    int strTail = m_filterBuffer.size();
    while(currentPos<strTail)
    {
        if (startPos<0)
        {
            int pos=findPosByRule(currentPos, true,ruleIndex);
            if (pos!=std::string::npos)
            {
                startPos = pos; /* 找到起始标志,继续查找结束标志 */
                currentPos = startPos + m_ruleVector[ruleIndex].startFlag.size();   /* 当前指针前移 */
                if (unFilterPos<startPos)/* 非法数据 */
                {
                    std::string tmp(m_filterBuffer,unFilterPos,startPos-unFilterPos);
                    strVector.push_back(tmp);
                    unFilterPos = startPos;
                }
                continue;
            }
            else
            {
                break;
            }
        }
        else if (endPos<0)
        {
            if (ruleIndex!=UNKNOWN_RULE)
            {
                int pos = findPosByRule(currentPos, false, ruleIndex);
                if (std::string::npos==pos)
                {
                    break;
                }
                else
                {
                    endPos = pos;
                    int len = endPos-startPos;
                    if (len>0)/* 中间有字符串则取走 */
                    {
                        std::string tmp(m_filterBuffer,startPos,len+m_ruleVector[ruleIndex].endFlag.size());
                        strVector.push_back(tmp);
                    }
                    /* 从结束符位置后开始搜索 */
                    currentPos = endPos + m_ruleVector[ruleIndex].endFlag.size();
                    unFilterPos = currentPos;
                    startPos = -1;
                    endPos = -1;
                    ruleIndex = UNKNOWN_RULE;
                }
                continue;
            }
        }
        else
        {
            TRACE_ERR_CLASS("can't be here!startPos=%d,endPos=%d\n",startPos,endPos);
        }
    }
    if (unFilterPos>0)
    {
        /* 去除已经处理过的字符串 */
        m_filterBuffer.erase(0,unFilterPos);
    }
    return strVector;
}
/**
 *  \brief  增加过滤规则
 *  \param  startFlag   开始标识
 *  \param  startFlagLen开始标识的长度
 *  \param  endFlag   结束标识
 *  \param  endFlagLen   结束标识的长度
 *  \return none
 *  \note   注意:使用该函数添加过滤规则时,先添加的优先级更高,
 *          请确保最特殊的规则放在最先添加,并且规则之间不能存
 *          在包含关系(如A规则是B规则的子集,即A规则范围小,B规
 *          则范围大,则A会被B规则屏蔽,将无法匹配到子集)!!!
 */
void StringFilter::addFilterRule(const char * startFlag, int startFlagLen, const char * endFlag, int endFlagLen)
{
    FilterRule_S rule;
    rule.startFlag = std::string(startFlag,startFlagLen);
    rule.endFlag = std::string(endFlag,endFlagLen);
    m_ruleVector.push_back(rule);
}

void StringFilter::clear()
{
    m_filterBuffer.clear();
    m_ruleVector.clear();
}


